#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"

#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include "../value.h"

#ifdef _TEST
#undef _TEST
#include "../value.c"
#define _TEST
#endif

Value * LuaReadValueAt(lua_State * L, int index)
{
    Value * val = 0;
    if (lua_isnumber(L, index)) {
        val = NumberValue(lua_tonumber(L, index));
    } else if (lua_isstring(L, index)) {
        size_t len = 0;
        const char * ptr = lua_tolstring (L, index, &len);
        val = StringValue(ptr, len);
    } else if (lua_istable(L, index)) {
        val = CreateValue();
        if (index < 0) {
            index = lua_gettop(L) + index + 1;
        }
        lua_pushnil(L);
        while(lua_next(L, index)) {
            Value * _key = LuaReadValueAt(L, -2);
            Value * _val = LuaReadValueAt(L, -1);
            ValueSetKV(val, _key, _val);
            lua_pop(L, 1);
        }
    }
    return val;
}

Value * LuaReadValue(lua_State * L, const char * name, ...) 
{
    int top = lua_gettop(L);
    int deep = 0;
    lua_getglobal(L, name); deep++;
    va_list args;
    va_start(args, name);
    while(1) {
        const char * key = va_arg(args, const char *);
        if (key == 0) {
            break;
        }
        if (!lua_istable(L, -1)) {
            lua_pop(L, deep);
            return 0;
        }
        lua_getfield(L, -1, key); deep++;
    }
    Value * val = LuaReadValueAt(L, -1);
    lua_pop(L, deep);
    assert(top == lua_gettop(L));
    return val;
}

void DumpValue(Value * val)
{
    if (val == 0) {
        printf("nil");
        return;
    }

    if (IsNumberValue(val)) {
        printf("%f", ValueToNumber(val));
    } else if (IsStringValue(val)) {
        printf("\"%s\"", ValueToString(val, 0));
    } else if (IsTableValue(val)) {
        printf("{");
        int i, max = TableValueArrayMaxIndex(val);
        for(i = 1; i <= max; i++) {
            DumpValue(TableValueAtIndex(val, i));
            printf(",");
        }

        ValuePair * cur = 0;
        while ((cur = TableValueHashNext(val, cur)) != 0) {
            printf("%s", ValueToString(cur->key, 0));
            printf("=");
            DumpValue(cur->val);
            printf(",");
        }
        printf("}");
    } else {
        printf("!!unknown type!!");
    }
}

int main(int argc, char * argv[])
{
    int i;
    lua_State * L = luaL_newstate();
    luaL_openlibs(L);

    for (i = 1; i < argc; i++) {
        if (luaL_dofile(L, argv[i]) != 0) {
            printf("load file %s failed\n", argv[i]);
            lua_close(L);
            return -1;
        }
    }

    Value * v = LuaReadValue(L, "value", "a", 0);

    DumpValue(v);
    printf("\n");

    DestoryValue(v);
    v = 0;

    lua_close(L);
    return 0;
}
